<template>
    <div>
        <el-card>
            <el-form :model="form" :inline="true" class="filter-form">
                <el-form-item label="角色名称">
                    <el-input v-model="form.roleName" placeholder="请输入角色名称" clearable />
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="fetchData">搜索</el-button>
                    <el-button type="default" @click="resetForm">重置</el-button>
                </el-form-item>
            </el-form>
        </el-card>
        <el-card style="margin-top: 5px;">
            <el-button type="primary" @click="centerDialogVisible = true">新增角色</el-button>
            <el-table border :data="tableData" class="table-main">
                <el-table-column align="center" label="序号" width="60" type="index" />
                <el-table-column align="center" label="角色名称" prop="roleName" />
                <el-table-column align="center" label="创建时间" width="170" prop="createTime" />
                <el-table-column align="center" label="更新时间" width="170" prop="updateTime" />
                <el-table-column align="center" label="操作" fixed="right" width="320">
                    <template #="{ row }">
                        <el-button icon="user" type="primary" @click="assignPermission(row.id)">分配权限</el-button>
                        <el-button icon="edit" type="primary" @click="editRole(row)">编辑</el-button>
                        <el-button icon="delete" type="danger" @click="deleteRole(row.id)">删除</el-button>
                    </template>
                </el-table-column>
            </el-table>
            <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize"
                :page-sizes="[10, 20, 30, 40]" layout="prev, pager, next, jumper, ->, sizes, total" :total="total"
                @change="fetchData" />
        </el-card>
        <el-dialog :title="roleEntry.id ? '编辑角色' : '新增角色'" v-model="centerDialogVisible" @closed="restRuleFormRef"
            width="30%" align-center>
            <el-form :model="roleEntry" label-width="auto" :rules="rules" ref="ruleFormRef" status-icon>
                <el-form-item label="角色名称" prop="roleName">
                    <el-input v-model="roleEntry.roleName" placeholder="请输入角色名称" clearable />
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button type="primary" @click="saveRoleInfo" :loading="loading">保存</el-button>
                <el-button type="default" @click="centerDialogVisible = false">取消</el-button>
            </template>
        </el-dialog>
        <el-drawer v-model="drawer" title="分配菜单和按钮权限">
            <el-tree ref="treeRef" style="max-width: 600px" :data="roleTreeData.roleTreeDataList" show-checkbox
                node-key="id" :default-checked-keys="roleCheckedKeys" :default-expanded-keys="roleExpandedKeys"
                :props="defaultProps" />
            <template #footer>
                <div style="flex: auto">
                    <el-button type="primary" :loading="loading" @click="savePermission">保存</el-button>
                    <el-button type="default" @click="drawer = false">取消</el-button>
                </div>
            </template>
        </el-drawer>
    </div>
</template>

<script setup lang='ts' name="ROLE">
import type { PermissionResult, RoleInfo } from "@/api/role/type";
import { reqRolePage, reqRoleUpdate, reqRoleAdd, reqRoleDelete, reqRoleDoAssign, reqRoleToAssign } from "@/api/role";
import type { ResponseData } from "@/api/type";
import type { FormInstance, FormRules, TreeInstance } from "element-plus";

let form = reactive({
    roleName: ''
});

let roleEntry = reactive({
    id: undefined,
    roleName: '',
});

let roleTreeData = reactive({
    roleId: -1,
    roleTreeDataList: [] as PermissionResult[]
})

const defaultProps = {
    children: 'children',
    label: 'name',
}

const roleCheckedKeys = ref<number[]>([]);
const roleExpandedKeys = ref<number[]>([]);

let currentPage = ref<number>(1)
let pageSize = ref<number>(10)
let total = ref<number>(0)
let tableData = ref<RoleInfo[]>()
let centerDialogVisible = ref<boolean>(false)
let ruleFormRef = ref<FormInstance>();
const loading = ref<boolean>(false);
const drawer = ref<boolean>(false);
const treeRef = ref<TreeInstance>();


const fetchData = () => {
    reqRolePage(currentPage.value, pageSize.value, form.roleName).then(res => {
        tableData.value = res.data.records
        total.value = res.data.total
    }).catch((error: ResponseData<String>) => {
        ElMessage.error(('获取角色失败。') + error.message);
    })
};


const resetForm = () => {
    form.roleName = ''
    fetchData()
}

const restRuleFormRef = () => {
    // 清空表单字段
    ruleFormRef.value?.resetFields();
    // 重置表单数据
    Object.assign(roleEntry, { id: undefined, roleName: '' })
}

const rules = ref<FormRules<RoleInfo>>({
    roleName: [{ required: true, message: '请输入角色名称', trigger: 'blur' }]
})

const editRole = (row: RoleInfo) => {
    centerDialogVisible.value = true
    Object.assign(roleEntry, row)
}

const saveRoleInfo = () => {
    ruleFormRef.value?.validate().then(() => {
        loading.value = true
        const action = roleEntry.id ? reqRoleUpdate : reqRoleAdd;
        action(roleEntry).then(() => {
            centerDialogVisible.value = false
            ElMessage.success(roleEntry.id ? '编辑角色成功。' : '新增角色成功。');
            fetchData()
        }).catch((error: ResponseData<String>) => {
            ElMessage.error((roleEntry.id ? '编辑角色失败。' : '新增角色失败。') + error.message);
        })
        loading.value = false
    })
}

const deleteRole = (id: number) => {
    ElMessageBox.confirm('确认删除该角色吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
    }).then(() => {
        reqRoleDelete(id).then(() => {
            ElMessage.success('删除角色成功。');
            fetchData()
        }).catch((error: ResponseData<String>) => {
            ElMessage.error('删除角色失败。' + error.message);
        })
    }).catch(() => {
        // 用户取消操作
    })
}

const assignPermission = (id: number) => {
    // Object.assign(roleTreeData, { roleId: -1, roleTreeDataList: [] })
    drawer.value = true
    roleTreeData.roleId = id
    reqRoleToAssign(id).then(res => {
        Object.assign(roleTreeData.roleTreeDataList, res.data)
        console.log("🚀 ~ assignPermission ~ roleTreeData:", roleTreeData)
        gainCheckedKeys(roleTreeData.roleTreeDataList)
    }).catch((error: ResponseData<String>) => {
        ElMessage.error('获取角色权限失败。' + error.message);
    })

}

const gainCheckedKeys = (data: PermissionResult[]) => {
    roleCheckedKeys.value = []
    roleExpandedKeys.value = []
    let array = [...data]
    let checkSet = new Set<number>()
    let selectPath: number[] = [];
    let level = 1;
    // 使用后序遍历
    while (array.length > 0) {
        const item = array.pop();
        if (!item) {
            continue;
        }

        // 判断是否子节点都遍历完,需要把父节点弹出
        if (level > item.level) {
            selectPath.splice(- (level - item.level));
            level = item.level
        }
        selectPath.push(item.id as number)
        if (item.children && item.children.length > 0) {
            array.push(...item.children)

        } else {
            // 叶子节点
            if (item.select) {
                roleCheckedKeys.value.push(item.id as number)
                selectPath.forEach(i => checkSet.add(i))
                // console.log("🚀 ~ gainCheckedKeys ~  selectPath:", item.name, selectPath)
            }

            selectPath.pop()
            level = item.level
        }
    }
    roleExpandedKeys.value = [...checkSet]
}

const savePermission = () => {
    loading.value = true
    const checkedKeys = treeRef.value?.getCheckedKeys() || [];
    const halfCheckedKeys = treeRef.value?.getHalfCheckedKeys() || [];
    const permissionIdList = [...checkedKeys, ...halfCheckedKeys].map(Number);
    const roleId = roleTreeData.roleId
    reqRoleDoAssign({ "roleId": roleId, "permissionIdList": permissionIdList }).then(() => {
        ElMessage.success('分配权限成功。');
        drawer.value = false
        fetchData()
    }).catch((error: ResponseData<String>) => {
        ElMessage.error('分配权限失败。' + error.message);
    })
    loading.value = false
}

onMounted(() => {
    fetchData()
})

</script>

<style scoped lang='scss'>
.filter-form {
    display: flex;
    justify-content: space-between;
}

.table-main {
    height: calc(100vh - $base-tabbar-height - 265px);
    margin: 10px 0px;
}
</style>